/**
 * 封装的3步：
 * 1. 私有化成员变量
 * 2. 设置getter和setter方法
 * 3. 在setter方法中设置业务规则
 */
public class Clock {
    public static String LOGO = "Rolex"; // 静态元素，属于类，有时候也称为类变量
    private int hour;  // 成员变量。属于对象，也称为实例变量，对象之间是互相隔离的。在当前类中，则可以通过this来引用
    private int minute; // 成员变量如果没有初始化，会启用默认值：数值类型都是0，布尔型是false，String是null，其他引用类型都是null
    private int second;

    static {
        System.out.println("静态代码块，是在实例元素初始化之前调用...");
    }

    public static void showLogo() { // 静态方法，属于类
        System.out.println(LOGO); // 静态方法中，可以访问静态变量
//        System.out.println(hour); // 静态方法中，无法访问实例元素
//        System.out.println(this.hour); // 静态方法中，无法访问实例元素
    }

    { // 纯代码块。类似于构造方法的效果，但是先于构造方法执行！一般不怎么用！
        // 可以像方法一样写代码
        System.out.println("代码块也是可以执行的...会在创建对象时，调用一次！");
    }
    // 构造方法的作用：初始化成员变量。构造方法一般位于成员变量之后，成员方法之前！
    // 一旦定义了自己的构造方法，编译器不再自动添加无参构造方法了。
    // 最佳实践：为了将来可以使用框架等高级特性自动创建对象，所以一般都需要主动编写无参构造方法！
    public Clock() {
        this(10, 10); // 调用带2个参数的构造方法
    }

    public Clock(int hour, int minute) {
        // 通过this可以调用其他重载的构造方法（注意参数匹配！）
        // 注意事项：使用this调用其它构造方法，要求必须是构造方法中的第一条语句！
        this(hour, minute, 0);
    }
    // 编程规范要求我们的标识符应该见名知义
    public Clock(int hour, int minute, int second) { // 带参构造方法，通过外界参数来更新成员变量。跟上面的无参构造方法形成重载关系。
        System.out.println("构造方法也是只在创建对象时，调用一次！");
        this.hour = hour; // 两侧都是参数中的hour，所以没有给成员变量hour赋值
        this.minute = minute; // 通过this来引用变量，就能明确的指向成员变量，从而解决变量名冲突问题
        this.second = second;
    }

    // 成员方法(成员方法不加static修饰符)
    public void showTime() {
        // printf是格式化输出方法，允许用%+占位符来控制输出格式
        System.out.printf("当前时间：%02d:%02d:%02d\n", hour, minute, second);
        System.out.println(LOGO); // 实例方法中，可以访问静态元素
    }

    public void updateTime(int h, int m, int s) {
        hour = h; // 用外部参数，刷新成员变量的值
        minute = m;
        second = s;
    }

    // getter方法的作用：在外部读取某个成员变量的值
    // 语法规则：get+变量名首字母大写，例如getHour();并返回该成员变量的值。
    public int getHour() {
        return hour;
    }

    // setter方法的作用：在外部改变某个成员变量的值
    // 语法规则：set+变量名首字母大写，例如setHour();并且需要接收一个外部参数，来更新成员变量
    public void setHour(int h) {
        hour = h;
    }

    public int getMinute() {
        return minute;
    }

    public void setMinute(int m) {
        if (m >= 0 && m < 60) { // 设置业务规则！提高程序的容错性！
            minute = m;
        }
    }

}
